parser grammar Anasin;

options {
  language = Java;
  tokenVocab = Analex;
}

@rulecatch {}

@header {
   package pl.grammar;
}

flex: 
   definiciones SEPARADOR reglas (SEPARADOR codigo)?;

definiciones: 
   (definicion|literal)+;

definicion: 
   IDENTIFICADOR expresion;

expresion: 
   CORCHETE_INI RANGO CORCHETE_FIN;

literal: 
   PORCENTAJE LLAVE_INI codigo PORCENTAJE LLAVE_FIN;

reglas: 
   (regla accion PUNTOYCOMA)+;

regla:
   ((referencia|opcion)(MAS|ASTERISCO)?)+;
   
referencia: 
   LLAVE_INI IDENTIFICADOR LLAVE_FIN;
   
opcion: 
   PARENTESIS_INI referencia (LOGICO_O referencia)* PARENTESIS_FIN;

accion: 
   IDENTIFICADOR (DOBLEMAS|DOBLEMENOS)?;

codigo: 
   (declaracion_tipo (variable PUNTOYCOMA|funcion)
   |declaracion_nulo_variable variable PUNTOYCOMA
   |declaracion_nulo_funcion funcion)+;

tipo:
   INT|CHAR;

declaracion_tipo: 
   tipo (ASTERISCO)? IDENTIFICADOR;

declaracion_nulo_variable: 
   VOID (ASTERISCO)? IDENTIFICADOR;

declaracion_nulo_funcion: 
   VOID IDENTIFICADOR;

declaracion_variable: 
   (declaracion_tipo|declaracion_nulo_variable) variable;

variable: 
   (CORCHETE_INI CORCHETE_FIN)?;

funcion: 
   PARENTESIS_INI (VOID|parametros) PARENTESIS_FIN LLAVE_INI cuerpo LLAVE_FIN;

parametros: 
   declaracion_variable (COMA declaracion_variable)*;

cuerpo: 
   ((asignacion|funcion_llamada|funcion_retorno) PUNTOYCOMA)*;

asignacion:
   IDENTIFICADOR IGUAL sentencia;

sentencia:
   ENTERO|funcion_llamada;

funcion_llamada:
   IDENTIFICADOR PARENTESIS_INI (funcion_parametros)? PARENTESIS_FIN;

funcion_parametros:
   (referencia_variable|ENTERO|CADENA)(COMA (referencia_variable|ENTERO|CADENA))*;

funcion_retorno: 
   RETURN ENTERO;

referencia_variable:
   (ASTERISCO)? IDENTIFICADOR (CORCHETE_INI ENTERO CORCHETE_FIN)?;

